<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <title>vm与vc</title>
    <!--   Vue -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>

<body>

    <div id="app">
        <h1>{{msg}}</h1>
        <user></user>
    </div>

    <script>

        // 这不是给Vue扩展counter属性
        // 这是给“Vue的原型对象”扩展一个counter属性
        Vue.prototype.counter = 100

        // 创建组件
        const user = Vue.extend({
            template: `
            <div>
                <h1>user组件</h1>
            </div>
            `,
            mounted() {
                // this是VueComponent实例
                // this不等于user，user是什么？  是一个全新的构造函数 VueComponent构造函数
                console.log('vc', this === user)

                // 为什么要这样设计？为了代码复用
                // 底层实现原理：
                // VueComponent.prototype.__proto__ = Vue.prototype
                console.log('vc.counter', this.counter)
            }
        })

        console.log("VueComponent.prototype.__proto__ === Vue.prototype", VueComponent.prototype.__proto__ === Vue.prototype)
        console.log(new user())

        const vm = new Vue({
            el: '#app',
            data: {
                msg: 'vm与vc',
            },
            components: {
                user
            },
            mounted() {
                // this是Vue实例
                console.log('vm', this)
            }
        })

        console.log("vm.counter", vm.counter)
        console.log("vm.__proto__.counterX", vm.__proto__.counter) //实际访问


        /*
          每一次都是一个新的对象，故不相等
         */
        let a = test
        console.log(new a())

        let b = test
        console.log(a === b)  // false,


        function test() {
            var sub = function user() {
                this.name = 'admin'
            }
            return sub
        }



        // prototype __proto__
        // 构造函数（函数本身又是一种类型，代表Vip类型）
        function Vip() {

        }

        // 这个prototype属性可以称为：显式的原型属性
        // 通过这个显式的原型属性可以获取：原型对象
        // 获取vip的原型对象
        let x = Vip.prototype

        // 通过vip可以创建实例
        let a1 = new Vip()
        let b1 = new Vip()
        let c1 = new Vip()
        // 对于实例来说，都有一个隐式的原型属性 __proto__
        // 注意：显式的（建议程序员使用）。隐式的（不建议程序员使用的）
        let x1 = a1.__proto__
        b1.__proto__
        c1.__proto__
        // 原型对象只有一个，其实原型对象都是共享的
        console.log(x === x1)  // true


        // 这不是给Vip扩展属性
        // 是在给“Vip的原型对象”扩展属性
        Vip.prototype.counter = 1000
        // 通过a实例可以获取counter属性吗？  可以访问。 为什么？原来是什么？
        // 访问原理：首先去a实例上找counter属性，如果a实例上没有counter属性的话，会沿着__proto__这个原型对象去找
        // 下面代码看起来表面是a上有一个counter属性，实际上不是a实例上的属性，是a实例对应的原型对象上的属性counter
        console.log(a.counter)
        console.log(a.__proto__.counter)  // 实际找到是这个

    </script>

</body>

</html>